package es.uji.viselab.network;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

import es.uji.viselab.LogLevel;
import es.uji.viselab.LogRecorder;
import es.uji.viselab.ViSeLabException;

public class Network {

	Socket socket = null;
	List<NetworkListener> eventListeners = new ArrayList<NetworkListener>();


	BufferedReader socketDataIn = null;
	PrintStream socketDataOut = null;
	private EncoderDecoder encDec;

	Network(EncoderDecoder ec) {
		this.encDec=ec;
	}

	
	public void addListener(NetworkListener nl){
	    eventListeners.add(nl);	
	}
	
	void sendData(String message) {
		socketDataOut.println(message);
	}

	String receiveData() {

		LogRecorder.log(LogLevel.INFO, "Waiting data from client");
		String message = null;
		try {
			message = socketDataIn.readLine();
			if (message != null) {
				String str = null;
				if (message.length() > 20)
					str = message.substring(0, 20) + "...";
				else
					str = message;
				LogRecorder.log(LogLevel.STATS, "Data has arrived, processing: " + str);
			}
		} catch (IOException e) {
			LogRecorder.log(LogLevel.ERROR, "Connection aborted", "Network.receiveData();");
			e.printStackTrace();
		}
		return message;
	}

	void close() throws ViSeLabException {
		try {
			socket.close();
			socketDataOut.close();
			socketDataIn.close();
		} catch (IOException e) {
			throw new ViSeLabException("Error when closing the connection", "Network.close()");
		}
	}

	
	public  void encodeAndSendData(DataPackage item){
		String message = encDec.encode(item);
		sendData(message);		
	}

	public List<DataPackage> receiveAndDecodeData() throws ViSeLabException{
		String s = receiveData();

		if (s != null) {
			return encDec.decode(s);
		} else
			return null;
	}
	
	public void createReceiver() throws ViSeLabException {
		try {
			socketDataIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		} catch (IOException e) {
			throw new ViSeLabException("Could not create receiver");
		}
	}

	public void createSender() throws ViSeLabException {

		try {
			socketDataOut = new PrintStream(socket.getOutputStream());
		} catch (IOException e) {
			throw new ViSeLabException("Could not create sender");
		}
	}

	
	public Socket getServiceSocket() {
		return socket;
	}

}
